/**
 * 封装的方法以及用法
 * 打开数据库
 * @param {object} dbName 数据库的名字
 * @param {string} storeName 仓库名称
 * @param {string} version 数据库的版本
 * @return {object} 该函数会返回一个数据库实例
 */
export function openDB(dbName, storeName, version = 1) {
	return new Promise((resolve, reject) => {
		//  兼容浏览器
		let indexedDB = window.indexedDB
		let db
		const request = indexedDB.open(dbName, version)
		request.onsuccess = function(event) {
			db = event.target.result // 数据库对象
			console.log('数据库打开成功')
			resolve(db)
		}

		request.onerror = function(event) {
			reject(event)
			console.log('数据库打开报错')
		}

		request.onupgradeneeded = function(event) {
			// 数据库创建或升级的时候会触发
			console.log('onupgradeneeded')
			db = event.target.result // 数据库对象
			let objectStore
			if (!db.objectStoreNames.contains(storeName)) {
				objectStore = db.createObjectStore(storeName, {
					keyPath: 'id'
				}) // 创建表
				// objectStore.createIndex('name', 'name', { unique: true }) // 创建索引 可以让你搜索任意字段
			}
		}
	})
}

/**
 * 新增数据
 * @param {object} db 数据库实例
 * @param {string} storeName 仓库名称
 * @param {string} data 数据
 */
export function addData(db, storeName, data) {
	let request = db.transaction([storeName], 'readwrite') // 事务对象 指定表格名称和操作模式（"只读"或"读写"）
		.objectStore(storeName) // 仓库对象
		.add(data)

	request.onsuccess = function(event) {
		console.log('数据写入成功')
	}

	request.onerror = function(event) {
		console.log('数据写入失败')
		throw new Error(event.target.error)
	}
}

/**
 * 通过主键读取数据
 * @param {object} db 数据库实例
 * @param {string} storeName 仓库名称
 * @param {string} key 主键值
 */
export function getDataByKey(db, storeName, key) {
	return new Promise((resolve, reject) => {
		let transaction = db.transaction([storeName]) // 事务
		let objectStore = transaction.objectStore(storeName) // 仓库对象
		let request = objectStore.get(key)

		request.onerror = function(event) {
			console.log('事务失败')
		}

		request.onsuccess = function(event) {
			console.log('主键查询结果: ', request.result)
			resolve(request.result)
		}
	})
}

/**
 * 通过游标读取数据
 * @param {object} db 数据库实例
 * @param {string} storeName 仓库名称
 */
export function cursorGetData(db, storeName) {
	let list = []
	let store = db.transaction(storeName, 'readwrite') // 事务
		.objectStore(storeName) // 仓库对象
	let request = store.openCursor() // 指针对象
	return new Promise((resolve, reject) => {
		request.onsuccess = function(e) {
			let cursor = e.target.result
			if (cursor) {
				// 必须要检查
				list.push(cursor.value)
				cursor.continue() // 遍历了存储对象中的所有内容
			} else {
				console.log('游标查询结果：', list)
				resolve(list)
			}
		}
		request.onerror = function(e) {
			reject(e)
		}
	})
}

/**
 * 通过索引读取数据
 * @param {object} db 数据库实例
 * @param {string} storeName 仓库名称
 * @param {string} indexName 索引名称
 * @param {string} indexValue 索引值
 */
export function getDataByIndex(db, storeName, indexName, indexValue) {
	let store = db.transaction(storeName, 'readwrite').objectStore(storeName)
	let request = store.index(indexName).get(indexValue)
	return new Promise((resolve, reject) => {
		request.onerror = function(e) {
			reject(e)
			console.log('事务失败')
		}
		request.onsuccess = function(e) {
			resolve(e.target.result)
		}
	})
}

/**
 * 通过索引和游标查询记录
 * @param {object} db 数据库实例
 * @param {string} storeName 仓库名称
 * @param {string} indexName 索引名称
 * @param {string} indexValue 索引值
 */
export function cursorGetDataByIndex(db, storeName, indexName, indexValue) {
	let list = []
	let store = db.transaction(storeName, 'readwrite').objectStore(storeName) // 仓库对象
	let request = store.index(indexName) // 索引对象
		.openCursor(IDBKeyRange.only(indexValue)) // 指针对象
	request.onsuccess = function(e) {
		let cursor = e.target.result
		if (cursor) {
			// 必须要检查
			list.push(cursor.value)
			cursor.continue() // 遍历了存储对象中的所有内容
		} else {
			console.log('游标索引查询结果：', list)
		}
	}
	request.onerror = function(e) {}
}

/**
 * 更新数据
 * @param {object} db 数据库实例
 * @param {string} storeName 仓库名称
 * @param {object} data 数据
 */
export function updateDB(db, storeName, data) {
	let request = db.transaction([storeName], 'readwrite') // 事务对象
		.objectStore(storeName) // 仓库对象
		.put(data)

	request.onsuccess = function() {
		console.log('数据更新成功')
	}

	request.onerror = function() {
		console.log('数据更新失败')
	}
}

/**
 * 删除数据
 * @param {object} db 数据库实例
 * @param {string} storeName 仓库名称
 * @param {object} id 主键值
 */
export function deleteDB(db, storeName, id) {
	let request = db.transaction([storeName], 'readwrite').objectStore(storeName).delete(id)

	request.onsuccess = function() {
		console.log('数据删除成功')
	}

	request.onerror = function() {
		console.log('数据删除失败')
	}
}

/**
 * 通过索引和游标删除指定的数据
 * @param {object} db 数据库实例
 * @param {string} storeName 仓库名称
 * @param {string} indexName 索引名
 * @param {object} indexValue 索引值
 */
export function cursorDelete(db, storeName, indexName, indexValue) {
	let store = db.transaction(storeName, 'readwrite').objectStore(storeName)
	let request = store.index(indexName) // 索引对象
		.openCursor(IDBKeyRange.only(indexValue)) // 指针对象
	request.onsuccess = function(e) {
		let cursor = e.target.result
		let deleteRequest
		if (cursor) {
			deleteRequest = cursor.delete() // 请求删除当前项
			deleteRequest.onerror = function() {
				console.log('游标删除该记录失败')
			}
			deleteRequest.onsuccess = function() {
				console.log('游标删除该记录成功')
			}
			cursor.continue()
		}
	}
	request.onerror = function(e) {}
}

/**
 * 删除数据库
 * @param {object} dbName 数据库名称
 */
export function deleteDBAll(dbName) {
	console.log(dbName)
	let deleteRequest = window.indexedDB.deleteDatabase(dbName)
	deleteRequest.onerror = function(event) {
		console.log('删除失败')
	}
	deleteRequest.onsuccess = function(event) {
		console.log('删除成功')
	}
}

/**
 * 关闭数据库
 * @param {object} db 数据库实例
 */
export function closeDB(db) {
	db.close()
	console.log('数据库已关闭')
}

export default {
	openDB,
	addData,
	getDataByKey,
	cursorGetData,
	getDataByIndex,
	cursorGetDataByIndex,
	updateDB,
	deleteDB,
	deleteDBAll,
	closeDB
}
